﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using Csla.Data;
using System.Data;
using System.Threading;
using Csla.Validation;
using System.Data.Common;
using System.Text.RegularExpressions;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;

namespace Asah.SiteWorx.Commerce
{
    [Serializable()]
    public class BillTo : BusinessBase<BillTo>
    {

        #region Business Methods

        private int _orderId = 0;
        private string _company = "";
        private string _firstName = "";
        private string _lastName = "";
        private string _address1 = "";
        private string _address2 = "";
        private string _city = "";
        private string _state = "";
        private string _zip = "";
        private string _phone = "";
        private string _email = "";

        [System.ComponentModel.DataObjectField(true, true)]
        public int OrderID
        {
            get
            {
                CanReadProperty("OrderID", true);
                return _orderId;
            }
        }

        public string Company
        {
            get
            {
                CanReadProperty("Company", true);
                return _company;
            }
            set
            {
                CanWriteProperty("Company", true);
                if (_company != value)
                {
                    _company = value;
                    PropertyHasChanged("Company");
                }
            }
        }

        public string FirstName
        {
            get
            {
                CanReadProperty("FirstName", true);
                return _firstName;
            }
            set
            {
                CanWriteProperty("FirstName", true);
                if (_firstName != value)
                {
                    _firstName = value;
                    PropertyHasChanged("FirstName");
                }
            }
        }

        public string LastName
        {
            get
            {
                CanReadProperty("LastName", true);
                return _lastName;
            }
            set
            {
                CanWriteProperty("LastName", true);
                if (_lastName != value)
                {
                    _lastName = value;
                    PropertyHasChanged("LastName");
                }
            }
        }

        public string Address1
        {
            get
            {
                CanReadProperty("Address1", true);
                return _address1;
            }
            set
            {
                CanWriteProperty("Address1", true);
                if (_address1 != value)
                {
                    _address1 = value;
                    PropertyHasChanged("Address1");
                }
            }
        }

        public string Address2
        {
            get
            {
                CanReadProperty("Address2", true);
                return _address2;
            }
            set
            {
                CanWriteProperty("Address2", true);
                if (_address2 != value)
                {
                    _address2 = value;
                    PropertyHasChanged("Address2");
                }
            }
        }

        public string City
        {
            get
            {
                CanReadProperty("City", true);
                return _city;
            }
            set
            {
                CanWriteProperty("City", true);
                if (_city != value)
                {
                    _city = value;
                    PropertyHasChanged("City");
                }
            }
        }

        public string State
        {
            get
            {
                CanReadProperty("State", true);
                return _state;
            }
            set
            {
                CanWriteProperty("State", true);
                if (_state != value)
                {
                    _state = value;
                    PropertyHasChanged("State");
                }
            }
        }

        public string Zip
        {
            get
            {
                CanReadProperty("Zip", true);
                return _zip;
            }
            set
            {
                CanWriteProperty("Zip", true);
                if (_zip != value)
                {
                    _zip = value;
                    PropertyHasChanged("Zip");
                }
            }
        }

        public string Phone
        {
            get
            {
                CanReadProperty("Phone", true);
                return _phone;
            }
            set
            {
                CanWriteProperty("Phone", true);
                if (_phone != value)
                {
                    _phone = value;
                    PropertyHasChanged("Phone");
                }
            }
        }

        public string Email
        {
            get
            {
                CanReadProperty("Email", true);
                return _email;
            }
            set
            {
                CanWriteProperty("Email", true);
                if (_email != value)
                {
                    _email = value;
                    PropertyHasChanged("Email");
                }
            }
        }

        protected override object GetIdValue()
        {
            return _orderId;
        }

        #endregion

        #region Validation Rules

        protected override void AddBusinessRules()
        {
            // add BusinessRules here
            ValidationRules.AddInstanceRule(CompanyNameRequired, "Company");
            ValidationRules.AddInstanceRule(FirstNameRequired, "FirstName");
            ValidationRules.AddInstanceRule(LastNameRequired, "LastName");
            ValidationRules.AddInstanceRule(Address1Required, "Address1");
            ValidationRules.AddInstanceRule(CityRequired, "City");
            ValidationRules.AddInstanceRule(StateRequired, "State");
            ValidationRules.AddInstanceRule(ZipRequired, "Zip");
            ValidationRules.AddInstanceRule(ValidZip, "Zip");
            ValidationRules.AddInstanceRule(PhoneRequired, "Phone");
            ValidationRules.AddInstanceRule(ValidPhone, "Phone");
            ValidationRules.AddInstanceRule(EmailRequired, "Email");
            ValidationRules.AddInstanceRule(ValidEmail, "Email");
        }

        private bool CompanyNameRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_company.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Company name is required.";
                return false;
            }
        }

        private bool FirstNameRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_firstName.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "First name is required.";
                return false;
            }
        }

        private bool LastNameRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_lastName.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Last name is required.";
                return false;
            }
        }

        private bool Address1Required(object target, Csla.Validation.RuleArgs e)
        {
            if (_address1.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Address is required.";
                return false;
            }
        }

        private bool CityRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_city.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "City is required.";
                return false;
            }
        }

        private bool StateRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_state.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "State is required.";
                return false;
            }
        }

        private bool ZipRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_zip.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Zip code is required.";
                return false;
            }
        }

        private bool ValidZip(object target, Csla.Validation.RuleArgs e)
        {
            Regex expression = new Regex(@"\d{5}(-\d{4})?");
            if (expression.IsMatch(_zip))
            {
                return true;
            }
            else
            {
                e.Description = "Invalid zip code format.";
                return false;
            }
        }

        private bool PhoneRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_phone.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Phone number is required.";
                return false;
            }
        }

        private bool ValidPhone(object target, Csla.Validation.RuleArgs e)
        {
            Regex expression = new Regex(@"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}");
            if (expression.IsMatch(_phone))
            {
                return true;
            }
            else
            {
                e.Description = "Invalid phone number format.";
                return false;
            }
        }

        private bool EmailRequired(object target, Csla.Validation.RuleArgs e)
        {
            if (_email.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Email address is required.";
                return false;
            }
        }

        private bool ValidEmail(object target, Csla.Validation.RuleArgs e)
        {
            Regex expression = new Regex(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
            if (expression.IsMatch(_email))
            {
                return true;
            }
            else
            {
                e.Description = "Invalid email format.";
                return false;
            }
        }
        #endregion

        #region Authorization Rules

        protected override void AddAuthorizationRules()
        {
            // add AuthorizationRules here
        }

        public static bool CanAddBillTo()
        {
            return true;
        }

        public static bool CanGetBillTo()
        {
            return true;
        }

        public static bool CanDeleteBillTo()
        {
            return false;
        }

        public static bool CanEditBillTo()
        {
            return false;
        }

        #endregion

        #region Factory Methods

        internal static BillTo NewBillTo()
        {
            return new BillTo();
        }

        internal static BillTo GetBillTo(SafeDataReader dr)
        {
            return new BillTo(dr);
        }

        private BillTo()
        {
            MarkAsChild();
            ValidationRules.CheckRules();
        }

        private BillTo(SafeDataReader dr)
        {
            MarkAsChild();
            Fetch(dr);
        }

        #endregion

        #region Data Access

        private void Fetch(SafeDataReader dr)
        {
            _orderId = dr.GetInt32("OrderId");
            _company = dr.GetString("Company");
            _firstName = dr.GetString("FirstName");
            _lastName = dr.GetString("LastName");
            _address1 = dr.GetString("Address1");
            _address2 = dr.GetString("Address2");
            _city = dr.GetString("City");
            _state = dr.GetString("State");
            _zip = dr.GetString("Zip");
            _phone = dr.GetString("Phone");
            _email = dr.GetString("Email");
            
            MarkOld();
            ValidationRules.CheckRules();
        }

        internal void Insert(Order order)
        {
            // if we're not dirty then don't update the database
            if (!this.IsDirty) return;

            Database db = DatabaseFactory.CreateDatabase("SiteWorxCommerce");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_OrderBillTos_AddBillTo");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
            db.AddInParameter(dbCommand, "OrderId", DbType.Int32, order.ID);
            db.AddInParameter(dbCommand, "Company", DbType.String, _company);
            db.AddInParameter(dbCommand, "FirstName", DbType.String, _firstName);
            db.AddInParameter(dbCommand, "LastName", DbType.String, _lastName);
            db.AddInParameter(dbCommand, "Address1", DbType.String, _address1);
            db.AddInParameter(dbCommand, "Address2", DbType.String, _address2);
            db.AddInParameter(dbCommand, "City", DbType.String, _city);
            db.AddInParameter(dbCommand, "State", DbType.String, _state);
            db.AddInParameter(dbCommand, "Zip", DbType.String, _zip);
            db.AddInParameter(dbCommand, "Phone", DbType.String, _phone);
            db.AddInParameter(dbCommand, "Email", DbType.String, _email);
            
            try
            {
                db.ExecuteNonQuery(dbCommand);
                dbCommand.Dispose();
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }

            MarkOld();
        }

        #endregion

    }
}
